﻿namespace Microsoft.Services.TestTools.UITesting.Html {
    using System.Diagnostics.CodeAnalysis;
    using Microsoft.VisualStudio.TestTools.UnitTesting;

    /// <summary>
    /// Base class used to simplify tests utilizing <see cref="Page"/>'s
    /// </summary>
    /// <typeparam name="T">The <see cref="Page"/> to launch and close</typeparam>
    /// <example>
    /// The test initialize and cleanup handles the 
    /// launching and closing of the Page instance
    /// <code>
    /// <![CDATA[
    /// [CodedUITest]
    /// public class HomeTests : PageTest<Home> {
    /// 
    ///     [TestMethod]
    ///     public void MainMenuContainsHome() {
    ///         Assert.IsTrue(TestedPage.MainMenuContainsItem("Home"));
    ///     }
    /// }
    /// ]]>
    /// </code>
    /// </example>
    public abstract class PageTest<T> where T : Page, new() {
        /// <summary>
        /// Gets or sets the tested page.
        /// </summary>
        /// <value>
        /// The tested page.
        /// </value>
        protected T TestedPage { get; set; }

        /// <summary>
        /// Initializes this instance.
        /// </summary>
        [TestInitialize]
        public virtual void Initialize() {
            TestedPage = Page.Launch<T>();
        }

        /// <summary>
        /// Cleanups this instance.
        /// </summary>
        [TestCleanup]
        public virtual void Cleanup() {
            TestedPage.Close();
        }

        #region Input Helpers

        /// <summary>
        /// The string creator
        /// </summary>
        [SuppressMessage(
            "StyleCop.CSharp.OrderingRules", 
            "SA1201:ElementsMustAppearInTheCorrectOrder", 
            Justification = "Reviewed. Suppression is OK here. Logical grouping")] 
        private readonly StringCreator _stringCreator = new StringCreator();

        /// <summary>
        /// Gets the string creator
        /// </summary>
        /// <remarks>
        /// For most cases the methods Name(), Amount(), Email(), Password() will probably be sufficient.
        /// Access this field if you want to generate more specialized strings
        /// </remarks>
        [SuppressMessage(
            "StyleCop.CSharp.OrderingRules",
            "SA1201:ElementsMustAppearInTheCorrectOrder",
            Justification = "Reviewed. Suppression is OK here. Logical grouping.")]
        protected StringCreator StringCreator {
            get { return _stringCreator; }
        }

        /// <summary>
        /// Generates a name
        /// </summary>
        /// <returns>A randomized name</returns>
        /// <remarks>Form input helper</remarks>
        /// <seealso cref="StringCreator"/>
        protected string Name() {
            return StringCreator.CreateName();
        }

        /// <summary>
        /// Generates an amount
        /// </summary>
        /// <returns>A random amount</returns>
        /// <remarks>Form input helper</remarks>
        /// <seealso cref="StringCreator"/>
        protected string Amount() {
            return StringCreator.CreateAmount();
        }

        /// <summary>
        /// Generates an email address
        /// </summary>
        /// <returns>A random email address</returns>
        /// <remarks>Form input helper</remarks>
        /// <seealso cref="StringCreator"/>
        protected string Email() {
            return StringCreator.CreateEmail();
        }

        /// <summary>
        /// Generates a password
        /// </summary>
        /// <returns>A random password</returns>
        /// <remarks>Form input helper</remarks>
        /// <seealso cref="StringCreator"/>
        protected string Password() {
            return StringCreator.CreatePassword();
        }

        #endregion
    }
}